package models

import (
	"errors"
	"fmt"
	"git.inedcn.com/ined/cmn"
	"rongyy/src/app"
	"rongyy/src/middlewares"
	"strings"
)

type PopularizationArticle struct {
	BaseModel        `xorm:"extends"`
	ArticleId        string       `json:"article_id"`
	Title            string       `json:"title"`  // 文章标题
	Author           string       `json:"author"` // 作者
	Digest           string       `json:"digest"`
	Content          string       `json:"content" xorm:"-"`
	Tag              int          `json:"tag"` // 标签
	ThumbMediaId     string       `json:"thumb_media_id"`
	Url              string       `json:"url"`
	ContentSourceUrl string       `json:"content_source_url"`
	Likes            int64        `json:"likes"` // 点赞
	Reads            int64        `json:"reads"` //被访问
	Type             string       `json:"type"`  //类别：文章，视频
	FeedId           string       `json:"feed_id"`
	FeedUrl          string       `json:"feed_url"`
	ThumbImgUrl      string       `json:"thumb_img_url"` // 视频的图片
	FeedSn           string       `json:"feed_sn"`       //视频号
	IsLink           int          `json:"is_link"`       //0 为正常  -1为不显示
	UpdatedAtWx      cmn.JsonTime `xorm:"updated_at_wx" json:"updated_at_wx"`
}

type PopularizationRecord struct {
	BaseModel `xorm:"extends"`
	MediaId   string `json:"media_id"`
	Tag       int    `json:"tag"`
	Like      int    `json:"like"`
}

type PopularizationSwiper struct {
	BaseModel `xorm:"extends"`
	MediaId   string `json:"media_id"`
	FeedId    string `json:"feed_id"`
	FeedSn    string `json:"feed_sn"`
	SwiperImg string `json:"swiper_img"` // swiper封面
}

type ReqPopularizationArticleFilter struct {
	Limit   int    `json:"limit"`
	Offset  int    `json:"offset"`
	Tag     int    `json:"tag"`
	Title   string `json:"title"`
	Type    string `json:"type"`
	Sort    string `json:"sort"`
	Keyword string `json:"keyword"`
}

type ReqPopularizationArticleDetail struct {
	MediaId string `json:"media_id"`
}

type PopularizationTag struct {
	BaseModel `xorm:"extends"`
	Name      string `json:"name"`
}

type PopularizationArticleTag struct {
	PopularizationArticle `xorm:"extends"`
	Name                  string `json:"tag_name"`
}

type TagTopList struct {
	Tag   int    `json:"tag"`
	Name  string `json:"name"`
	Count int64  `json:"count"`
}

type StatisReads struct {
	Type  string `json:"type"`
	Value int64  `json:"value"`
}

func (pa *PopularizationArticle) TableName() string {
	return "popularization_article"
}

func (pa *PopularizationArticle) Insert() (*PopularizationArticle, error) {
	_, err := app.DB().Insert(pa)
	if err != nil {
		middlewares.Logger.Println("insert user fail", err)
		return nil, err
	}
	return pa, err
}

func (pa *PopularizationArticle) InsertOrUpdate(pm *PopularizationArticle) error {
	p := &PopularizationArticle{}
	has, err := app.DB().Where("url = ? or title = ?", pm.Url, pm.Title).Get(p)
	if err != nil {
		middlewares.Logger.Println("find by url PopularizationArticle", err)
		return err
	}
	if has {
		//_, err = app.DB().Where("media_id =?", pm.Url).Cols("title", "author", "digest", "url", "thumb_media_id", "content_source_url").Update(pa)
		//if err != nil {
		//	middlewares.Logger.Println("update popularization fail", err)
		//	return err
		//}
		return nil
	} else {
		app.DB().Insert(pm)
		if err != nil {
			middlewares.Logger.Println("insert popularization fail", err)
			return err
		}
	}
	return nil
}

func (pa *PopularizationArticle) Update(id int64) (*PopularizationArticle, error) {
	_, err := app.DB().Where("id =?", id).Cols("title", "author").Update(pa)
	if err != nil {
		middlewares.Logger.Println("update user fail", err)
		return nil, err
	}
	fmt.Println(pa.CreatedAt)
	return pa, err
}

func (pa *PopularizationArticle) ArticleUpdateTag(id int64, tag int) (*PopularizationArticle, error) {
	pa.Tag = tag
	_, err := app.DB().ID(id).Cols("tag").Update(pa)
	if err != nil {
		middlewares.Logger.Println("update user fail", err)
		return nil, err
	}
	return pa, err
}

func (pa *PopularizationArticle) InsertTag(tag *PopularizationTag) error {
	_, err := app.DB().Table("popularization_tags").Insert(tag)
	if err != nil {
		middlewares.Logger.Println("PopularizationTag  insert fail", err)
		return err
	}
	return nil
}

func (pa *PopularizationArticle) FindTagById(id int64) (*PopularizationTag, bool, error) {
	npt := &PopularizationTag{}
	has, err := app.DB().Table("popularization_tags").Where("id = ?", id).Get(npt)
	if err != nil {
		middlewares.Logger.Println("PopularizationTag  find by id  fail", err)
		return nil, false, err
	}
	return npt, has, nil
}

func (pa *PopularizationArticle) UpdateTag(tag *PopularizationTag) error {
	_, err := app.DB().Table("popularization_tags").Where("id = ?", tag.Id).Cols("name").Update(tag)
	if err != nil {
		middlewares.Logger.Println("PopularizationTag  update fail", err)
		return err
	}
	return nil
}

func (pa *PopularizationArticle) FindTagByName(Name string) (bool, error) {
	npt := &PopularizationTag{}
	has, err := app.DB().Table("popularization_tags").Where("name = ?", Name).Get(npt)
	if err != nil {
		middlewares.Logger.Println("PopularizationTag find fail", err)
		return false, err
	}
	return has, nil
}

func (pa *PopularizationArticle) QueryTag() ([]PopularizationTag, int64, error) {
	pts := make([]PopularizationTag, 0)
	total, err := app.DB().Table("popularization_tags").FindAndCount(&pts)
	if err != nil {
		middlewares.Logger.Println("find by id doctor", err)
		return nil, 0, err
	}
	return pts, total, err
}

func (pa *PopularizationArticle) FindById(id int64) (*PopularizationArticle, bool, error) {
	u := &PopularizationArticle{}
	has, err := app.DB().ID(id).Get(u)
	if err != nil {
		middlewares.Logger.Println("find by id doctor", err)
		return nil, false, err
	}
	return u, has, err
}

func (pa *PopularizationArticle) FindByMediaId(url string) (*PopularizationArticle, bool, error) {
	p := &PopularizationArticle{}
	has, err := app.DB().Where("url = ?", url).Get(p)
	if err != nil {
		middlewares.Logger.Println("find by id doctor", err)
		return nil, false, err
	}
	return p, has, err
}

/*
*
用于pc端
*/
func (sss *PopularizationArticle) Query(req ReqPopularizationArticleFilter) ([]PopularizationArticleTag, int64, error) {
	pas := make([]PopularizationArticleTag, 0)
	s := app.DB().Table("popularization_article").Join("LEFT", "popularization_tags", "popularization_article.tag = popularization_tags.id")

	if req.Tag != 0 {
		s.Where("tag=?", req.Tag)
	}

	if req.Title != "" {
		title := fmt.Sprintf("%%%s%%", req.Title)
		s.Where("title Like ?", title)
	}

	if req.Type != "" {
		ty := fmt.Sprintf("%%%s%%", req.Type)
		s.Where("type Like ?", ty)
	}

	total, err := s.Where("is_link=0").Limit(req.Limit, req.Offset).OrderBy("popularization_article.updated_at_wx desc").FindAndCount(&pas)
	if err != nil {
		middlewares.Logger.Println("ERROR - User Query failed ", err)
		return nil, 0, errors.New("获取科普文章列表失败")
	}

	return pas, total, nil
}

/*
*
用于pc端
*/
func (sss *PopularizationArticle) QueryPc(req ReqPopularizationArticleFilter) ([]PopularizationArticleTag, int64, error) {
	pas := make([]PopularizationArticleTag, 0)
	s := app.DB().Table("popularization_article").Join("LEFT", "popularization_tags", "popularization_article.tag = popularization_tags.id")

	if req.Tag != 0 {
		s.Where("tag=?", req.Tag)
	}

	if req.Title != "" {
		title := fmt.Sprintf("%%%s%%", req.Title)
		s.Where("title Like ?", title)
	}

	if req.Type != "" {
		ty := fmt.Sprintf("%%%s%%", req.Type)
		s.Where("type Like ?", ty)
	}

	s.Limit(req.Limit, req.Offset)
	if req.Sort != "" {
		s.OrderBy("popularization_article.updated_at_wx " + req.Sort)
	} else {

	}

	total, err := s.FindAndCount(&pas)
	if err != nil {
		middlewares.Logger.Println("ERROR - User Query failed ", err)
		return nil, 0, errors.New("获取科普文章列表失败")
	}

	return pas, total, nil
}

func (pa *PopularizationArticle) InsertRecord(record *PopularizationRecord) error {
	_, err := app.DB().Table("popularization_records").Insert(record)
	if err != nil {
		middlewares.Logger.Println("PopularizationTag  insert fail", err)
		return err
	}
	return nil
}

func (pa *PopularizationArticle) InsertSwiper(sw *PopularizationSwiper) error {
	_, err := app.DB().Table("popularization_swiper").Insert(sw)
	if err != nil {
		middlewares.Logger.Println("PopularizationTag  insert fail", err)
		return err
	}
	return nil
}

func (pa *PopularizationArticle) SwiperList() ([]PopularizationSwiper, int64, error) {
	pas := make([]PopularizationSwiper, 0)
	total, err := app.DB().Table("popularization_swiper").FindAndCount(&pas)
	if err != nil {
		middlewares.Logger.Println("PopularizationTag  insert fail", err)
		return nil, 0, err
	}
	return pas, total, nil
}

func (pa *PopularizationArticle) AddLike(record *PopularizationRecord) error {
	_, err := app.DB().Table("popularization_records").Insert(record)
	_, err = app.DB().Exec("update popularization_article set  `likes` = `likes` + 1 where media_id = ?", record.MediaId)
	//err := app.DB().SQL("select * from  popularization_article where media_id=?", record.MediaId).Find(&PopularizationArticles)
	if err != nil {
		middlewares.Logger.Println("PopularizationTag  insert fail", err)
		return err
	}
	return nil
}

func (pa *PopularizationArticle) AddRecord(record *PopularizationRecord) error {
	_, err := app.DB().Table("popularization_records").Insert(record)
	_, err = app.DB().Exec("update popularization_article set  `reads` = `reads` + 1 where media_id = ?", record.MediaId)
	if err != nil {
		middlewares.Logger.Println("PopularizationTag  AddRecord fail", err)
		return err
	}
	return nil
}

func (pa *PopularizationArticle) TagTopList() ([]TagTopList, error) {
	qqs := make([]TagTopList, 0)
	err := app.DB().SQL("SELECT tag, pt.name, count(*) as count from popularization_records pr LEFT JOIN popularization_tags pt on pr.tag = pt.id  GROUP BY tag ORDER BY COUNT(*) DESC").Find(&qqs)
	if err != nil {
		middlewares.Logger.Println("PopularizationTag  insert fail", err)
		return nil, err
	}
	return qqs, nil
}

func (pa *PopularizationArticle) StatisRead(req *ReqPopularizationArticleFilter) ([]StatisReads, error) {
	pas := make([]StatisReads, 0)
	err := app.DB().SQL("SELECT title as 'type', `reads` as 'value' from popularization_article ORDER BY `reads` DESC  LIMIT 0,?", req.Limit).Find(&pas)
	if err != nil {
		middlewares.Logger.Println("Popularization statisRead fail", err)
		return nil, err
	}
	return pas, nil
}

func (uc *PopularizationArticle) DeleteSwiper(id int64) error {
	_, err := app.DB().Table("popularization_swiper").ID(id).Delete(&PopularizationSwiper{})
	if err != nil {
		middlewares.Logger.Println("ERROR - AddSwiper failed ", err)
		return err
	}
	return nil
}

func (uc *PopularizationArticle) UpdateThumbImg(req *PopularizationArticle) error {
	_, err := app.DB().Table("popularization_article").ID(req.Id).Cols("thumb_img_url").Update(req)
	if err != nil {
		middlewares.Logger.Println("ERROR - UpdateThumbImg failed ", err)
		return err
	}
	return nil
}

func (uc *PopularizationArticle) Link(id int64) error {
	pa := &PopularizationArticle{}
	pa.Id = id
	pa.IsLink = 0
	_, err := app.DB().Table("popularization_article").ID(id).Cols("is_link").Update(pa)
	if err != nil {
		middlewares.Logger.Println("ERROR - Link failed ", err)
		return err
	}
	return nil
}

func (uc *PopularizationArticle) UnLink(id int64) error {
	pa := &PopularizationArticle{}
	pa.Id = id
	pa.IsLink = -1
	_, err := app.DB().Table("popularization_article").ID(id).Cols("is_link").Update(pa)
	if err != nil {
		middlewares.Logger.Println("ERROR - Link failed ", err)
		return err
	}
	return nil
}

func (uc *PopularizationArticle) Delete(id int64) error {
	pa := &PopularizationArticle{}
	pa.Id = id
	_, err := app.DB().Table("popularization_article").ID(id).Delete(pa)
	if err != nil {
		middlewares.Logger.Println("ERROR - Link failed ", err)
		return err
	}
	return nil
}

func (uc *PopularizationArticle) FindByKeyName(req *ReqPopularizationArticleFilter) ([]PopularizationArticle, int64, error) {
	pt := make([]PopularizationTag, 0)
	_, err := app.DB().Table("popularization_tags").FindAndCount(&pt)
	fmt.Println(pt)
	ids := make([]int64, 0)
	for _, item := range pt {
		if strings.Contains(req.Keyword, item.Name) {
			fmt.Println(item)
			ids = append(ids, item.Id)
		}
	}
	fmt.Println(ids)
	ps := make([]PopularizationArticle, 0)
	total, err := app.DB().Table("popularization_article").Limit(req.Limit, req.Offset).In("tag", ids).FindAndCount(&ps)
	if err != nil {
		middlewares.Logger.Println("find by id doctor", err)
		return nil, 0, err
	}
	return ps, total, err
}
